﻿#include "stdafx.h"
#include "main_data_c.h"
#include "utils/StringUtils.h"
#include "loadRes.h"
#include "audio/dsoundHelp.h"
#include "scene/SceneManage.h"
#include "network/GameNet.h"
#include "utils/Debug.h"
#include "ui/textInput.h"

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"GlU32.Lib")
#pragma comment(lib,"Shlwapi.lib")
#pragma comment(lib,"WinMM.Lib")
#pragma comment(lib,"version.Lib")
#pragma comment(lib,"WS2_32.Lib")
#pragma comment(lib,"AdvAPI32.Lib")
#pragma comment(lib,"dsound.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib, "Crypt32.lib")

bool parseCmdLine(const char* cmdLine, char* outIp, WORD* outPort);
HWND CreateMainWindow(HINSTANCE hInstance);
bool initOpenGLContext();
void sub_426980(BYTE*);
LRESULT CALLBACK WndProc_403BF0(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

//#define dispatchPackets MuDispatchPacket_40C1B0
#define dispatchPackets gameNet->dispatchPackets

extern "C"
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    assert(131397592 == offsetof(MainData, dword_81D54B4));
	u_short port;
	struct tagMSG Msg;
	DEVMODEA DevMode;

    mainData.isDebug_81C4978 = true;

	muInit();
	readConfig();
	readMuText();
	readDataEncDec();
	GameNet* gameNet = GameNet::getInstance();
	gameNet->getProtocol()->initEncDec("Data\\Enc1.dat", "Data\\Dec2.dat");

	if (parseCmdLine(lpCmdLine, mainData.connectIpBuf_54CA4AC, &port))
	{
		connectIp_4828FC = mainData.connectIpBuf_54CA4AC;
		connectPort_482900 = port;
	}
	else
	{
		connectIp_4828FC = cfg_lastIp;
		connectPort_482900 = cfg_lastPort;
	}

	if (!windowMode_47C2CC)
	{
		DevMode.dmSize = 124;
		DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
		DevMode.dmPelsWidth = g_wndWidth;
		DevMode.dmPelsHeight = g_wndHeight;
		DevMode.dmDisplayFlags = 0;
		if (ChangeDisplaySettingsA(&DevMode, 0) < 0)
			MessageBoxA(0, "无法调整显示属性!", "MU", 0x40u);
	}
	//hInstdword_54CA694 = (int)hInstance;
    mainData.hWnd1_54CA690 = CreateMainWindow(hInstance);
	initOpenGLContext();
	ShowWindow(mainData.hWnd1_54CA690, nShowCmd);
	UpdateWindow(mainData.hWnd1_54CA690);
	if ((unsigned int)g_wndWidth > 800)
        mainData.fontHeight_7BA8530 = 15;
	else
        mainData.fontHeight_7BA8530 = 13;

    mainData.hfont1_54CA6A0 = CreateFontA(mainData.fontHeight_7BA8530 - 1, 0, 0, 0, FW_NORMAL, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, mainData.textBmd_7B7BCE8[0]);
    mainData.hfont2_54CA6A4 = CreateFontA(mainData.fontHeight_7BA8530 - 1, 0, 0, 0, FW_BOLD, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, mainData.textBmd_7B7BCE8[0]);
    mainData.hfont3_54CA6A8 = CreateFontA(2 * mainData.fontHeight_7BA8530 - 2, 0, 0, 0, FW_BOLD, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, mainData.textBmd_7B7BCE8[0]);
	setlocale(LC_ALL, ".ACP");

	if (mainData.soundOnOff_54CA688)
		initDirectSound(mainData.hWnd1_54CA690);
	SetTimer(mainData.hWnd1_54CA690, 1000, 20000, 0);
	srand((int)time(0));
	for (size_t i = 0; i < 100; i++)
	{
        mainData.randNums_54CA4F8[i] = rand() % 360;
	}

    mainData.dword_54CA4E8 = (BYTE*)new_mem_byte(rand() % 100 + 1);
    mainData.newData384h_7B7BCD8 = (BYTE*)new_mem_byte(0x384u);
    mainData.newData900h1_7B7BCE4 = (BYTE*)new_mem_byte(0x900u);
    mainData.newData900h2_7B786D0 = (BYTE*)new_mem_byte(0x900u);
    mainData.newData3700h1_7BA8518 = (BYTE*)new_mem_byte(0x3700u);
    mainData.newData3700h2_7B786C8 = (BYTE*)new_mem_byte(0x3700u);
    mainData.newData3ACA0h_79DBE84 = (BYTE*)new_mem_byte(0x3ACA0u);
    mainData.newData570h_7B786D4 = (BYTE*)new_mem_byte(0x570u);
	memset(mainData.newData384h_7B7BCD8, 0, 0x384u);
	memset(mainData.newData900h1_7B7BCE4, 0, 0x900u);
	memset(mainData.newData900h2_7B786D0, 0, 0x900u);
	memset(mainData.newData3700h1_7BA8518, 0, 0x3700u);
	memset(mainData.newData3700h2_7B786C8, 0, 0x3700u);
	memset(mainData.newData3ACA0h_79DBE84, 0, 0x3ACA0u);
	memset(mainData.newData570h_7B786D4, 0, 0x570u);
    mainData.myGameObjInfo_7B786CC = (MyGameObjInfo*)mainData.newData570h_7B786D4;
	sub_426980(mainData.newData570h_7B786D4);
    mainData.dword_79DBE88 = mainData.newData3ACA0h_79DBE84;
	while (1)
	{
		while (!PeekMessageA(&Msg, 0, 0, 0, 0))
		{
			updateScene(mainData.hdc1_54CA698);
			dispatchPackets();
		}
		if (!GetMessageA(&Msg, 0, 0, 0))
			break;
		TranslateMessage(&Msg);
		DispatchMessageA(&Msg);
		dispatchPackets();
	}
	sub_403940();
	return Msg.wParam;
}

extern "C"
int __stdcall SocketData_send(BYTE *data,int len,BOOL encode)
{
    //printBinary(data, len);
	return 1;
}

extern "C"
int __stdcall SocketData_recv(BYTE *data,int len)
{
	//TraceB(data,len);
	return 1;
}

bool parseCmdLine(const char* cmdLine, char* outIp, WORD* outPort)
{
	bool result;
	char szBuf[128];

	result = readCmdLine_option(cmdLine, 'u', szBuf);
	if (result)
	{
		strcpy(outIp, szBuf);
		result = readCmdLine_option(cmdLine, 'p', szBuf);
		if (result)
		{
			*outPort = atoi(szBuf);
		}
	}
	return result;
}

HWND CreateMainWindow(HINSTANCE hInstance)
{
	HWND result;
	WNDCLASSA WndClass;

	WndClass.style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = WndProc;
    WndClass.lpfnWndProc = WndProc_403BF0;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIconA(0, "IDI_ICON1");
	WndClass.hCursor = LoadCursorA(0, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
	WndClass.lpszMenuName = 0;
	WndClass.lpszClassName = g_wndClassName;
	RegisterClassA(&WndClass);
	if (windowMode_47C2CC)
		result = CreateWindowExA(
			0,
			g_wndClassName,
			g_wndClassName,
			WS_OVERLAPPEDWINDOW,
			0,
			0,
			g_wndWidth + 8,
			g_wndHeight + 34,
			0,
			0,
			hInstance,
			0);
	else
		result = CreateWindowExA(
			0,
			g_wndClassName,
			g_wndClassName,
			WS_POPUP,
			0,
			0,
			g_wndWidth,
			g_wndHeight,
			0,
			0,
			hInstance,
			0);
	return result;
}

void freeDisplay()
{
	if (mainData.hglrc_54CA69C)
	{
		if (!wglMakeCurrent(0, 0))
			MessageBoxA(0, "Release Of DC And RC Failed.", "Error", 0x40u);
		if (!wglDeleteContext(mainData.hglrc_54CA69C))
			MessageBoxA(0, "Release Rendering Context Failed.", "Error", 0x40u);
        mainData.hglrc_54CA69C = 0;
	}
	DeleteDC(mainData.hdc2_54CA68C);
	if (mainData.hdc1_54CA698 && !ReleaseDC(mainData.hWnd1_54CA690, mainData.hdc1_54CA698))
	{
		MessageBoxA(0, "OpenGL Release Error.", "Error", 0x40u);
        mainData.hdc1_54CA698 = 0;
	}
	if (!windowMode_47C2CC)
	{
		ChangeDisplaySettingsA(0, 0);
		ShowCursor(true);
	}
}

// 设置hglrc,显示窗口
bool initOpenGLContext()
{
	bool result = false;
	int iPixelFormat;
	PIXELFORMATDESCRIPTOR ppfd;
	const char* err;

	memset(&ppfd, 0, sizeof(ppfd));
	ppfd.iPixelType = PFD_TYPE_RGBA;
	ppfd.cColorBits = 16;
	ppfd.cDepthBits = 16;
	ppfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	ppfd.nVersion = 1;
	ppfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
	mainData.hdc1_54CA698 = GetDC(mainData.hWnd1_54CA690);

	if (mainData.hdc1_54CA698)
	{
		iPixelFormat = ChoosePixelFormat(mainData.hdc1_54CA698, &ppfd);
		if (iPixelFormat)
		{
			if (SetPixelFormat(mainData.hdc1_54CA698, iPixelFormat, &ppfd))
			{
                mainData.hglrc_54CA69C = wglCreateContext(mainData.hdc1_54CA698);
				if (mainData.hglrc_54CA69C)
				{
					if (wglMakeCurrent(mainData.hdc1_54CA698, mainData.hglrc_54CA69C))
					{
						ShowWindow(mainData.hWnd1_54CA690, SW_SHOW);
						SetForegroundWindow(mainData.hWnd1_54CA690);
						SetFocus(mainData.hWnd1_54CA690);
						result = true;
					}
					else err = "OpenGL Make Current Error.";
				}
				else err = "OpenGL Create Context Error.";
			}
			else err = "OpenGL Set Pixel Format Error.";
		}
		else err = "OpenGL Choose Pixel Format Error.";
	}
	else err = "OpenGL Get DC Error.";

	if (!result) {
		freeDisplay();
		MessageBoxA(0, mainData.textBmd_7B7BCE8[4], err, 0x30u);
	}
	return result;
}

void sub_426980(BYTE* data)
{
	BYTE* p = data + 520;
	int count = 12;
	sub_426900();
	do
	{
		*(WORD*)p = 0xffff;
		p += 68;
		--count;
	} while (count);
	*((DWORD*)(data + 0x538)) = 0;
	*((DWORD*)(data + 0x53c)) = 0;
}

void onMsgDestroy()
{
    mainData.byte_54CA6B0 = 1;
    if (nScene_482904 == 5)
    {
        sub_44CDA0("Data\\HotKey.txt");
        sub_44CD00("Data\\Macro.txt");
    }
    sub_448180();
    sub_4486C0();
    sub_442790();
    DeleteObject(mainData.hfont1_54CA6A0);
    DeleteObject(mainData.hfont2_54CA6A4);
    GameNet::getInstance()->close();
    for (size_t i = 0; i < 400; i++)
    {
        sub_401480(i);
    }

    for (size_t i = 0; i < 1300; i++)
    {
        DelTexture_456C70(i);
    }

    releaseDSound_401530();
    freeDisplay();
    PostQuitMessage(0);
}

LRESULT CALLBACK WndProc_403BF0(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        onMsgDestroy();
        break;
    case WM_ACTIVATE:
        mainData.byte_54CA6C4 = wParam;
        break;
    case WM_SETCURSOR:
        //ShowCursor(FALSE);
        break;
    case WM_TIMER:
        sub_403240();
        break;
    case WM_USER:
        switch (lParam)
        {
        case FD_READ:
            GameNet::getInstance()->onAsyncRecv();
            break;
        case FD_WRITE:
            GameNet::getInstance()->onAsyncSend();
            break;
        case FD_CLOSE:
            gamePrintLog("", mainData.textBmd_7B7BCE8[3], 1);
            GameNet::getInstance()->close();
            break;
        }
        break;
    }

    if (!mainData.byte_54CA6C4)
        return DefWindowProcA(hWnd, msg, wParam, lParam);

    mainData.lButtonDbClick_81C17D0 = 0;

    switch (msg)
    {
    case WM_MOUSEMOVE:
        mainData.curMouseXrate_81C17B4 = 640 * LOWORD(lParam) / g_wndWidth;
        mainData.curMouseYrate_81C17B0 = 480 * HIWORD(lParam) / g_wndHeight;
        break;
    case WM_LBUTTONDOWN:
        mainData.dword_54CA6C0 = 0;
        mainData.beginLButtonUp_81C1678 = 0;
        if (!mainData.curLButtonDown_81C17F8)
            mainData.beginLButtonDown_81C1660 = 1;
        mainData.curLButtonDown_81C17F8 = 1;
        break;
    case WM_LBUTTONUP:
        mainData.dword_54CA6C0 = 0;
        mainData.beginLButtonDown_81C1660 = 0;
        if (mainData.curLButtonDown_81C17F8)
            mainData.beginLButtonUp_81C1678 = 1;
        mainData.curLButtonDown_81C17F8 = 0;
        break;
    case WM_LBUTTONDBLCLK:
        mainData.dword_54CA6C0 = 0;
        mainData.lButtonDbClick_81C17D0 = 1;
        break;
    case WM_RBUTTONDOWN:
        mainData.dword_54CA6C0 = 0;
        mainData.beginRButtonUp_81C17C8 = 0;
        if (!mainData.curRButtonDown_81C17E4)
            mainData.beginRButtonDown_81C1804 = 1;
        mainData.curRButtonDown_81C17E4 = 1;
        break;
    case WM_RBUTTONUP:
        mainData.dword_54CA6C0 = 0;
        mainData.beginRButtonDown_81C1804 = 0;
        if (mainData.curRButtonDown_81C17E4)
            mainData.beginRButtonUp_81C17C8 = 1;
        mainData.curRButtonDown_81C17E4 = 0;
        break;
    case WM_CHAR:
        if (onMsgChar(wParam, lParam)) return 0;
        break;
    case WM_SYSKEYDOWN:
        if (wParam == VK_MENU)
            g_showGroundItemName = !g_showGroundItemName;
        break;
    //case WM_IME_STARTCOMPOSITION:
    //    mainData.byte_54CA6B1 = 1;
    //    break;
    //case WM_IME_ENDCOMPOSITION:
    //    mainData.byte_54CA6B1 = 0;
    //    break;
    //case WM_IME_COMPOSITION:
    //{
    //    BYTE* p = mainData.byte_7C41C7C + 4 * mainData.strBufIndex_7C41CF8;
    //    if (wParam || p[0] || p[1] || p[2])
    //        wParam = wParam;
    //    p[0] = wParam >> 40;
    //    p[1] = wParam >> 32;
    //    p[2] = 0;
    //    break;
    //}
    default:
        break;
    }
    return DefWindowProcA(hWnd, msg, wParam, lParam);
}
